package team.bluepen.supermarket.service.recommend;

import org.springframework.stereotype.Service;
import team.bluepen.supermarket.data.entity.Product;
import team.bluepen.supermarket.service.ProductProvider;
import team.bluepen.supermarket.service.recommend.dto.ItemDTO;
import team.bluepen.supermarket.service.recommend.service.Recommend;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author RollW
 */
@Service
public class RecommendService {
    private final ProductProvider productProvider;

    public RecommendService(ProductProvider productProvider) {
        this.productProvider = productProvider;
    }

    public List<Product> recommendByUser(long userId) {
        List<Product> products = productProvider.getProducts();
        List<ItemDTO> itemList = Recommend.userCfRecommend(
                userId % 100, products);

        List<Long> itemIds = itemList.stream()
                .map(ItemDTO::getRawId)
                .collect(Collectors.toList());
        List<Product> result = products.stream()
                .filter(e -> itemIds.contains(e.getId()))
                .collect(Collectors.toList());
        return result.size() > 10 ? result.subList(0, 10) : result;
    }

    public List<Product> recommendByProduct(long productId) {
        List<Product> products = productProvider.getProducts();
        List<ItemDTO> itemList = Recommend.itemCfRecommend(
                productId % 100, distinctById(products));

        List<Long> itemIds = itemList.stream()
                .map(ItemDTO::getRawId)
                .distinct()
                .collect(Collectors.toList());
        List<Product> result = products.stream()
                .filter(e -> itemIds.contains(e.getId()))
                .collect(Collectors.toList());
        return result.size() > 10 ? result.subList(0, 10) : result;
    }

    private List<Product> distinctById(List<Product> products) {
        return new ArrayList<>(products.stream()
                .collect(Collectors.toMap(Product::getId, e -> e, (e1, e2) -> e1))
                .values()
        );
    }
}
